package com.example.smartwaterapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartwaterapi.entity.User;
import com.example.smartwaterapi.mapper.UserMapper;
import com.example.smartwaterapi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 用户服务实现类
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    // 移除字段注入
    private PasswordEncoder passwordEncoder;

    // 使用setter注入
    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }
    
    // 用于缓存最近登录的用户信息，key是code，value是用户ID
    private Map<String, Long> recentLoginUsers = new HashMap<>();
    // 限制缓存大小
    private static final int MAX_CACHE_SIZE = 100;

    /**
     * 根据手机号获取用户
     */
    @Override
    @Cacheable(value = "user", key = "'phone:' + #phone", unless = "#result == null")
    public User getByPhone(String phone) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, phone);
        return getOne(wrapper);
    }

    /**
     * 根据微信OpenID获取用户
     */
    @Override
    @Cacheable(value = "user", key = "'openid:' + #openid", unless = "#result == null")
    public User getByOpenid(String openid) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getOpenid, openid);
        return getOne(wrapper);
    }

    /**
     * 更新用户饮水目标
     */
    @Override
    @CacheEvict(value = "user", key = "'id:' + #userId")
    public boolean updateDailyGoal(Long userId, Integer dailyGoal) {
        User user = new User();
        user.setId(userId);
        user.setDailyGoal(dailyGoal);
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }

    /**
     * 更新用户提醒设置
     */
    @Override
    @CacheEvict(value = "user", key = "'id:' + #userId")
    public boolean updateReminderSettings(Long userId, Integer enabled, Integer interval) {
        User user = new User();
        user.setId(userId);
        user.setReminderEnabled(enabled);
        if (interval != null) {
            user.setReminderInterval(interval);
        }
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }

    /**
     * 分页查询用户列表
     */
    @Override
    public Page<User> listUsers(Integer pageNum, Integer pageSize, String keyword) {
        Page<User> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        
        // 如果有关键字，添加模糊查询条件
        if (StringUtils.hasText(keyword)) {
            wrapper.like(User::getNickname, keyword)
                   .or()
                   .like(User::getPhone, keyword);
        }
        
        wrapper.orderByDesc(User::getCreatedAt);
        return page(page, wrapper);
    }
    
    /**
     * 更新用户积分
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "user", key = "'id:' + #userId")
    public boolean updatePoints(Long userId, Integer points) {
        // 获取用户
        User user = getById(userId);
        if (user == null) {
            return false;
        }
        
        // 计算新积分
        int newPoints = user.getPoints() + points;
        if (newPoints < 0) {
            // 积分不足
            return false;
        }
        
        // 更新积分
        user = new User();
        user.setId(userId);
        user.setPoints(newPoints);
        
        // 如果是增加积分，同时更新累计积分
        if (points > 0) {
            int newTotalPoints = user.getTotalPoints() != null ? user.getTotalPoints() + points : points;
            user.setTotalPoints(newTotalPoints);
        }
        
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }
    
    /**
     * 通过手机号更新用户微信信息
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public boolean updateUserByPhone(String phone, String openid, String unionid, String sessionKey) {
        if (!StringUtils.hasText(phone)) {
            log.error("手机号不能为空");
            return false;
        }
        
        try {
            LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(User::getPhone, phone);
            User user = getOne(wrapper);
            
            if (user == null) {
                log.error("未找到手机号对应的用户: {}", phone);
                return false;
            }
            
            // 更新用户微信信息
            User updateUser = new User();
            updateUser.setId(user.getId());
            updateUser.setOpenid(openid);
            updateUser.setUnionid(unionid);
            updateUser.setSessionKey(sessionKey);
            updateUser.setLastLoginTime(LocalDateTime.now());
            updateUser.setUpdatedAt(LocalDateTime.now());
            
            boolean result = updateById(updateUser);
            log.info("通过手机号更新用户微信信息: phone={}, result={}", phone, result);
            return result;
        } catch (Exception e) {
            log.error("通过手机号更新用户微信信息失败: phone={}", phone, e);
            return false;
        }
    }
    
    /**
     * 通过微信公众号openid获取用户
     */
    @Override
    @Cacheable(value = "user", key = "'wxopenid:' + #wxOpenid", unless = "#result == null")
    public User getByWxOpenid(String wxOpenid) {
        if (!StringUtils.hasText(wxOpenid)) {
            return null;
        }
        return baseMapper.selectByWxOpenid(wxOpenid);
    }
    
    /**
     * 通过微信公众号openid获取用户ID
     */
    @Override
    public Long getUserIdByWxOpenid(String wxOpenid) {
        User user = getByWxOpenid(wxOpenid);
        return user != null ? user.getId() : null;
    }

    /**
     * 通过微信unionid获取用户
     */
    @Override
    @Cacheable(value = "user", key = "'unionid:' + #unionid", unless = "#result == null")
    public User getByUnionid(String unionid) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUnionid, unionid);
        return getOne(wrapper);
    }

    /**
     * 更新用户的微信公众号openid
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public boolean updateWxOpenid(Long userId, String wxOpenid) {
        if (userId == null) {
            log.error("用户ID不能为空");
            return false;
        }
        
        try {
            int result = baseMapper.updateWxOpenid(userId, wxOpenid);
            log.info("更新用户微信公众号openid: userId={}, wxOpenid={}, result={}", userId, wxOpenid, result > 0);
            return result > 0;
        } catch (Exception e) {
            log.error("更新用户微信公众号openid失败: userId={}, wxOpenid={}", userId, wxOpenid, e);
            return false;
        }
    }
    
    @Override
    public boolean updatePassword(String phone, String password) {
        if (!StringUtils.hasText(phone) || !StringUtils.hasText(password)) {
            return false;
        }
        
        // 通过手机号查询用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        User user = getOne(queryWrapper);
        if (user == null) {
            return false;
        }
        
        // 调用已有的方法更新密码
        return updatePassword(user.getId(), password);
    }
    
    // 已有的方法，保留
    public boolean updatePassword(Long userId, String password) {
        if (userId == null || !StringUtils.hasText(password)) {
            return false;
        }
        
        User user = getById(userId);
        if (user == null) {
            return false;
        }
        
        // 更新密码
        User updateUser = new User();
        updateUser.setId(userId);
        updateUser.setUnlockPassword(password); // 这里应该有加密处理
        updateUser.setLastPasswordChange(LocalDateTime.now());
        updateUser.setUpdatedAt(LocalDateTime.now());
        
        return updateById(updateUser);
    }
    
    @Override
    public User register(String phone, String password, String nickname) {
        // 检查用户是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getPhone, phone);
        if (getOne(queryWrapper) != null) {
            throw new RuntimeException("该手机号已注册");
        }
        
        // 创建新用户
        User user = new User();
        user.setPhone(phone);
        user.setNickname(nickname);
        user.setUuid(UUID.randomUUID().toString().replace("-", ""));
        
        // 设置密码（这里应该有加密处理）
        user.setUnlockPassword(password);
        user.setLastPasswordChange(LocalDateTime.now());
        
        // 设置默认值
        user.setDailyGoal(2000); // 默认饮水目标
        user.setReminderEnabled(0); // 🔕 默认关闭提醒，避免打扰用户
        user.setReminderInterval(60); // 默认提醒间隔60分钟
        user.setStatus(1); // 默认状态正常
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        
        // 保存用户
        save(user);
        // Assuming log is available, otherwise remove this line
        // System.out.println("用户注册成功: " + nickname + ", ID: " + user.getId());
        
        return user;
    }
    
    /**
     * 创建或更新微信用户
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(value = "user", allEntries = true)
    public User createOrUpdateWechatUser(String openid, String sessionKey, String nickname, String avatar, Integer gender) {
        // 先查找是否存在该用户
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid, openid);
        User user = getOne(queryWrapper);
        
        if (user == null) {
            // 创建新用户
            user = new User();
            // 生成随机UUID作为用户唯一标识
            user.setUuid(UUID.randomUUID().toString().replace("-", ""));
            user.setOpenid(openid);
            user.setSessionKey(sessionKey);
            user.setNickname(nickname);
            user.setAvatar(avatar);
            user.setGender(gender);
            user.setDailyGoal(2000); // 默认饮水目标
            user.setReminderEnabled(0); // 🔕 默认关闭提醒，避免打扰用户
            user.setReminderInterval(60); // 默认提醒间隔60分钟
            user.setStatus(1); // 默认状态正常
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            user.setLastLoginTime(LocalDateTime.now());
            
            // 保存用户
            save(user);
            // System.out.println("创建微信用户: " + nickname + ", openid: " + openid + ", ID: " + user.getId());
            
            // 重新获取一次用户，确保有ID
            user = getOne(queryWrapper);
            
            return user;
        } else {
            // System.out.println("找到现有微信用户, 更新前检查: ID=" + user.getId() + ", openid=" + openid);
            
            // 重要：确保用户ID不为null
            Long userId = user.getId();
            
            // 如果ID为null，尝试从数据库中查询
            if (userId == null) {
                userId = baseMapper.selectIdByOpenid(openid);
                // System.out.println("通过直接查询获取ID: " + userId);
                
                if (userId != null) {
                    // 通过ID重新查询完整的用户信息
                    User fullUser = getById(userId);
                    if (fullUser != null) {
                        // System.out.println("通过ID重新查询用户成功: ID=" + userId + ", openid=" + fullUser.getOpenid());
                        user = fullUser;
                    }
                }
            }
            
            // 最终检查，如果还是null，记录错误
            if (userId == null) {
                // System.err.println("错误: 从数据库查询到的用户ID为null! openid=" + openid);
                return user; // 返回当前用户，由上层处理
            }

            // 更新现有用户信息
            User updateUser = new User();
            updateUser.setId(userId); // 使用确认的userId
            
            // 只有当用户昵称为空或为默认的"微信用户"时，才更新昵称
            if (user.getNickname() == null || user.getNickname().isEmpty() || "微信用户".equals(user.getNickname())) {
                updateUser.setNickname(nickname);
            }
            
            updateUser.setSessionKey(sessionKey);
            updateUser.setGender(gender);
            
            // 只有当用户头像为空时，才更新头像
            if (user.getAvatar() == null || user.getAvatar().isEmpty()) {
                if (avatar != null) {
                    updateUser.setAvatar(avatar);
                }
            }
            
            updateUser.setLastLoginTime(LocalDateTime.now());
            updateUser.setUpdatedAt(LocalDateTime.now());
            
            // 记录更新前的信息
            // System.out.println("准备更新用户: ID=" + updateUser.getId() + ", nickname=" + nickname);
            
            // 更新用户信息
            boolean updated = updateById(updateUser);
            
            if (!updated) {
                // System.err.println("无法更新用户，ID=" + userId);
                // 如果更新失败，再次尝试直接通过SQL更新
                // 修改这里，避免更新昵称
                String userNickname = user.getNickname();
                if (userNickname == null || userNickname.isEmpty() || "微信用户".equals(userNickname)) {
                    userNickname = nickname;
                } else {
                    // 保留原有昵称
                    nickname = userNickname;
                }
                int rowsAffected = baseMapper.updateUserByOpenid(userNickname, sessionKey, gender, avatar, LocalDateTime.now(), openid);
                // System.out.println("通过直接SQL更新结果: 影响行数=" + rowsAffected);
            } else {
                // System.out.println("最终修复用户ID成功: " + userId);
            }
            
            // 返回更新后的用户信息（重新查询以获取最新数据）
            return getById(userId);
        }
    }
    
    /**
     * 创建新用户(内部方法，用于回退策略)
     */
    private User createNewUser(String openid, String sessionKey, String nickname, String avatar, Integer gender) {
        User user = new User();
        // 生成随机UUID作为用户唯一标识
        user.setUuid(UUID.randomUUID().toString().replace("-", ""));
        user.setOpenid(openid);
        user.setSessionKey(sessionKey);
        user.setNickname(nickname);
        user.setAvatar(avatar);
        user.setGender(gender);
        user.setDailyGoal(2000); // 默认饮水目标
        user.setReminderEnabled(0); // 🔕 默认关闭提醒，避免打扰用户
        user.setReminderInterval(60); // 默认提醒间隔
        user.setMembershipLevel("basic"); // 默认会员等级
        user.setPoints(0);
        user.setTotalPoints(0);
        user.setStatus(1); // 正常状态
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        user.setLastLoginTime(LocalDateTime.now()); // 设置首次登录时间
        
        // 保存新用户
        save(user);
        // System.out.println("作为回退策略创建新微信用户: " + user.getNickname() + ", ID: " + user.getId() + ", UUID: " + user.getUuid());
        
        return user;
    }
    
    /**
     * 检查用户是否存在
     */
    @Override
    public boolean checkUserExists(String openid) {
        if (!StringUtils.hasText(openid)) {
            return false;
        }
        
        Long userId = getUserIdByOpenid(openid);
        return userId != null;
    }
    
    /**
     * 根据最近使用的微信code查找用户
     */
    @Override
    public User getRecentLoginUserByCode(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        
        // 从缓存中查找
        Long userId = recentLoginUsers.get(code);
        if (userId != null) {
            return getById(userId);
        }
        
        // 从数据库中查找最近登录的用户
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getLastLoginCode, code)
               .orderByDesc(User::getLastLoginTime)
               .last("LIMIT 1");
        
        return getOne(wrapper);
    }
    
    /**
     * 更新用户最后登录信息
     */
    @Override
    @CacheEvict(value = "user", key = "'id:' + #userId")
    public boolean updateLastLogin(Long userId, String code) {
        if (userId == null || !StringUtils.hasText(code)) {
            return false;
        }
        
        // 更新用户登录信息
        User user = new User();
        user.setId(userId);
        user.setLastLoginTime(LocalDateTime.now());
        user.setLastLoginCode(code);
        user.setUpdatedAt(LocalDateTime.now());
        
        boolean result = updateById(user);
        
        // 更新内存缓存
        if (result) {
            // 如果缓存过大，清理一部分
            if (recentLoginUsers.size() >= MAX_CACHE_SIZE) {
                // 简单清理策略：清空一半
                int count = 0;
                for (String key : recentLoginUsers.keySet()) {
                    recentLoginUsers.remove(key);
                    count++;
                    if (count >= MAX_CACHE_SIZE / 2) {
                        break;
                    }
                }
            }
            
            // 添加到缓存
            recentLoginUsers.put(code, userId);
        }
        
        return result;
    }

    @Override
    public Long getUserIdByOpenid(String openid) {
        if (!StringUtils.hasText(openid)) {
            return null;
        }
        // 使用更可靠的方法获取用户ID
        Long userId = baseMapper.getIdByOpenid(openid);
        
        // 如果新方法失败，尝试旧方法
        if (userId == null) {
            userId = baseMapper.selectIdByOpenid(openid);
        }
        
        return userId;
    }
    
    /**
     * 创建用户并确保返回ID
     */
    @Override
    public User createUserAndGetId(User user) {
        if (user == null) {
            return null;
        }
        
        try {
            // 确保时间字段不为null
            if (user.getCreatedAt() == null) {
                user.setCreatedAt(LocalDateTime.now());
            }
            if (user.getUpdatedAt() == null) {
                user.setUpdatedAt(LocalDateTime.now());
            }
            
            // 使用新的插入方法获取ID
            int result = baseMapper.insertUserAndReturnId(user);
            if (result > 0 && user.getId() != null) {
                return user;
            }
            
            // 如果新方法失败，尝试旧方法
            if (save(user)) {
                // 如果ID仍为null，再次查询
                if (user.getId() == null && StringUtils.hasText(user.getOpenid())) {
                    Long userId = getUserIdByOpenid(user.getOpenid());
                    if (userId != null) {
                        user.setId(userId);
                    }
                }
                return user;
            }
            
            return null;
        } catch (Exception e) {
            log.error("创建用户失败", e);
            return null;
        }
    }

    @Override
    public User getRecentLoginUserByPartialCode(String partialCode) {
        if (!StringUtils.hasText(partialCode) || partialCode.length() < 6) {
            return null;
        }

        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.like(User::getLastLoginCode, partialCode + "%")
                        .orderByDesc(User::getLastLoginTime)
                        .last("LIMIT 1");
            return getOne(queryWrapper);
        } catch (Exception e) {
            // Assuming log is available, otherwise remove this line
            // System.err.println("通过部分code查询用户失败: " + e.getMessage());
            return null;
        }
    }
} 